﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Net;
using System.Web;
using tiDE;
using System.IO;
using HtmlAgilityPack;

namespace GenerateTI83PlusIncDocumentation
{
    class Program
    {
        /// <summary>
        /// {0} is the url to shorten, {1} is the custom alias
        /// </summary>
        const string TinyUrlCreation = "http://tinyurl.com/create.php?source=indexpage&url={0}&submit=Make+TinyURL%21&alias={1}";

        /// <summary>
        /// {0} is the BCall address
        /// </summary>
        const string WikiTIBCallUrl = "http://wikiti.brandonw.net/index.php?title=83Plus:BCALLs:{0}";

        /// <summary>
        /// {0} is the RAM address
        /// </summary>
        const string WikiTIRAMAreaUrl = "http://wikiti.brandonw.net/index.php?title=83Plus:RAM:{0}";

        static void Main(string[] args)
        {
            // Format:
            // <documentation file="filename">
            //   <symbol name="name" moreinfo="url"><![CDATA[Documentation]]/></symbol>
            // </documentation>

            XDocument outputDocument = new XDocument();
            outputDocument.Add(new XElement("documentation"));
            outputDocument.Root.SetAttributeValue("file", "ti83plus.inc");
            Console.WriteLine("ti83plus.inc Documentation Generator");
            Console.WriteLine("This process may take some time.  Please be patient.");
            Assembler asm = new Assembler();
            asm.Assemble("include \"ti83plus.inc\"\ninc hl", Directory.GetCurrentDirectory() + "\\", "");
            SavedInclude ti83plusInc = Assembler.SavedIncludeFiles.Values.ElementAt(0);
            int index = 0;
            foreach (KeyValuePair<string, Assembler.Constant> pair in ti83plusInc.Constants)
            {
                Console.Clear();
                Console.WriteLine("Processing {0}/{1}: {2}", index + 1, ti83plusInc.Constants.Count, pair.Key);
                Console.Title = "Progress: " + (index + 1) + "/" + ti83plusInc.Constants.Count;
                XElement thisElement = new XElement("symbol");
                thisElement.SetAttributeValue("name", pair.Key);
                if (pair.Key.StartsWith("_"))
                {
                    byte[] values = Assembler.BytesFromBinary(pair.Value.Value);
                    ushort value = ushort.Parse(AddCharIfNecissary(values[0].ToString("x")), System.Globalization.NumberStyles.HexNumber);
                    if (values.Length == 2)
                        value = ushort.Parse(AddCharIfNecissary(values[0].ToString("x")) +
                            AddCharIfNecissary(values[1].ToString("x")), System.Globalization.NumberStyles.HexNumber);
                    if (value >= 0x4000 && value < 0x8130)
                    {
                        Console.WriteLine("Value: " + value.ToString("x"));
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(WikiTIBCallUrl, value.ToString("x").ToUpper()));
                        try
                        {
                            HttpWebResponse resp = (HttpWebResponse)request.GetResponse();
                            HtmlDocument document = new HtmlDocument();
                            Stream stream = resp.GetResponseStream();
                            document.Load(stream);
                            stream.Close();
                            HtmlNode node = document.GetElementbyId("bodyContent");
                            string description = "";
                            List<string> inputs = new List<string>();
                            List<string> outputs = new List<string>();
                            string registersDestroyed = "";
                            string comments = "";
                            try
                            {
                                int pOffset = 0;
                                if (node.SelectNodes("p")[0].InnerHtml.Contains("br"))
                                    pOffset++;
                                description = node.SelectNodes("p")[2 + pOffset].InnerText.Replace("\r", "").Replace("\n", "");
                                foreach (HtmlNode liNode in node.SelectSingleNode("ul").SelectNodes("li"))
                                {
                                    inputs.Add(liNode.InnerText.Replace("\r", "").Replace("\n", ""));
                                }
                                foreach (HtmlNode liNode in node.SelectNodes("ul")[1].SelectNodes("li"))
                                {
                                    outputs.Add(liNode.InnerText.Replace("\r", "").Replace("\n", ""));
                                }
                                try
                                {
                                    registersDestroyed = node.SelectNodes("ul")[2 + pOffset].SelectSingleNode("li").InnerText.Replace("\r", "").Replace("\n", "");
                                }
                                catch { }
                                try
                                {
                                    comments = node.SelectNodes("p")[3 + pOffset].InnerText.Replace("\r", "").Replace("\n", "");
                                }
                                catch { }
                                string doc = pair.Value.Name + "\n\n" + description + "\n\nInputs:\n";
                                foreach (string input in inputs)
                                {
                                    doc += "-" + input + "\n";
                                }
                                doc += "\n\nOutputs:\n";
                                foreach (string output in outputs)
                                {
                                    doc += "-" + output + "\n";
                                }
                                if (registersDestroyed != "")
                                {
                                    doc += "\n\nRegisters Destroyed:\n" + registersDestroyed;
                                }
                                if (comments != "")
                                {
                                    doc += "\n\nComments:\n" + comments;
                                }
                                thisElement.SetAttributeValue("moreinfo", string.Format(WikiTIBCallUrl, value.ToString("x").ToUpper()));
                                thisElement.Add(new XCData(doc));
                                outputDocument.Root.Add(thisElement);
                            }
                            catch
                            {
                            }
                        }
                        catch { }
                    }
                }
                index++;
            }
            Stream outStream = File.Create("ti83plus.inc.xml");
            outputDocument.Save(outStream);
            outStream.Close();
        }

        static string AddCharIfNecissary(string x)
        {
            if (x.Length == 1)
                return "0" + x;
            return x;
        }
    }
}
